package cgl.sensorgrid.xml.binary.adapters;

import java.io.*;
import nux.xom.io.*;
import nu.xom.NodeFactory;
import nux.xom.pool.XOMUtil;
import nu.xom.Builder;
import nux.xom.binary.*;
import nu.xom.*;
import nux.xom.tests.BinaryXMLConverter;

public class BNUX {

    private static StreamingSerializerFactory factory; // = new StreamingSerializerFactory();
    private static BinaryXMLCodec codec;// = new BinaryXMLCodec();
    private static ByteArrayOutputStream out;
    private static StreamingSerializer ser ;
    private static NodeFactory redirector;

    public BNUX() {
        factory = new StreamingSerializerFactory();
        codec = new BinaryXMLCodec();
        out = new ByteArrayOutputStream();
    }



    /**
     *
     * @param in InputStream
     * @param out OutputStream
     */
    public static void Xml2Bnux(InputStream in, OutputStream out) {
        //from http://dsd.lbl.gov/nux/index.html
        try {
            // streaming conversion of standard textual XML to bnux binary XML:
//            System.out.println("BNUX::Converting xml to bnux...");
//            long start = System.currentTimeMillis();
            StreamingSerializerFactory factory = new StreamingSerializerFactory();

            StreamingSerializer serializer = factory.createBinaryXMLSerializer(
                    out, 0);

            NodeFactory redirector = XOMUtil.getRedirectingNodeFactory(
                    serializer);
            new Builder(redirector).build(in); // performs streaming conversion
//            long end = System.currentTimeMillis();
//            System.out.println("Xml2Bnux completed in " + (end-start) + " ms.");
            in.close();
            out.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    /**
     *
     * @param str String
     * @return byte[]
     */
    public static byte[] Xml2Bnux(String str) {
        try {
            System.out.println("BNUX::Converting xml to bnux...");
            long start = System.currentTimeMillis();

            ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            Xml2Bnux(bis, out);

            byte[] by = out.toByteArray();
            long end = System.currentTimeMillis();
            System.out.println("Xml2Bnux completed in " + (end-start) + " ms.");
            return by;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     *
     * @param in InputStream
     * @param out OutputStream
     */
    public static void Bnux2Xml(InputStream in, OutputStream out) {
        try {
//            System.out.println("BNUX::Converting bnux to xml...");
//            long start = System.currentTimeMillis();
            StreamingSerializerFactory factory = new StreamingSerializerFactory();
            StreamingSerializer serializer = factory.createXMLSerializer(
                    out, "UTF-8");
            NodeFactory redirector = XOMUtil.getRedirectingNodeFactory(serializer);
            new BinaryXMLCodec().deserialize(in, redirector); // performs streaming conversion
//            long end = System.currentTimeMillis();
//            System.out.println("Bnux2Xml completed in " + (end-start) + " ms.");
            in.close();
            out.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (BinaryParsingException ex) {
            ex.printStackTrace();
        }
    }

    /**
       *
       * @param str String
       * @return byte[]
       */
      public static ByteArrayOutputStream Bnux2Xml(InputStream in) {
          try {
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              Bnux2Xml(in, out);
              return out;
          } catch (Exception ex) {
              ex.printStackTrace();
              return null;
          }
    }


    public byte[] readFile(File file){
        try {
//            BufferedReader br = new BufferedReader(new FileReader(file));
//            String line="";
//            System.out.println("here");
//            while(br.ready()){
//                line+=br.readLine();
//            }
//
            DataInputStream dis = new DataInputStream(new FileInputStream(file));
            byte[] filebytes = new byte[(int) file.length()];
            dis.readFully(filebytes);

            return filebytes;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }


    //// NEW METHODS

    /**
     *
     * @param inFile String
     * @param outFile String
     * @throws Exception
     */
    public static void bnux2xml(String inFile, String outFile) throws Exception {
      InputStream in = new FileInputStream(inFile);
      OutputStream out = null;
      NodeFactory redirector = null;
      out = new FileOutputStream(outFile);
      StreamingSerializer ser = factory.createXMLSerializer(out, "UTF-8");
      redirector = XOMUtil.getRedirectingNodeFactory(ser);
      long start = System.currentTimeMillis();
      codec.deserialize(in, redirector); // perform conversion
      System.out.print( (System.currentTimeMillis() - start));
    }

    /**
     *
     * @param inFile String
     * @param outFile String
     * @throws Exception
     */
    public static void xml2bnux(String inFile, String outFile) throws Exception {
      int compressionLevel = Integer.getInteger(
          "nux.xom.tests.BinaryXMLConverter.compressionLevel", 0).intValue();

        InputStream in = new FileInputStream(inFile);
      File file = new File(inFile);
      OutputStream out = null;
      out = new FileOutputStream(outFile);

      NodeFactory redirector = null;
      StreamingSerializer ser = codec.createStreamingSerializer(out,
          compressionLevel);
      redirector = XOMUtil.getRedirectingNodeFactory(ser);
      long start = System.currentTimeMillis();
//    new Builder(redirector).build(file); // perform conversion
      new Builder(redirector).build(in); // perform conversion
      System.out.print( (System.currentTimeMillis() - start));
    }

  //////////////////////


  /**
   *
   * @param inFile String
   * @param outFile String
   * @throws Exception
   */
  public static ByteArrayOutputStream bnux2xml(ByteArrayInputStream in) throws Exception {
      out = new ByteArrayOutputStream();
      ser = factory.createXMLSerializer(out, "UTF-8");
      redirector = XOMUtil.getRedirectingNodeFactory(ser);
      codec.deserialize(in, redirector);
      return out;
  }

  /**
   *
   * @param inFile String
   * @param outFile String
   * @throws Exception
   */
  public static ByteArrayOutputStream xml2bnux(ByteArrayInputStream in) throws Exception {
    int compressionLevel = Integer.getInteger(
        "nux.xom.tests.BinaryXMLConverter.compressionLevel", 0).intValue();
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    NodeFactory redirector = null;
    StreamingSerializer ser = codec.createStreamingSerializer(out,
        compressionLevel);
    redirector = XOMUtil.getRedirectingNodeFactory(ser);
    long start = System.currentTimeMillis();
//    new Builder(redirector).build(file); // perform conversion
    new Builder(redirector).build(in); // perform conversion
    System.out.print( (System.currentTimeMillis() - start));
    return out;
  }

    public static void main(String[] args) {
        try {
            BNUX b = new BNUX();
            //XML2BNUX
            byte[] xmlFile = b.readFile(new File("C:/projects/XML/data/DEMOFLORIDA.gml"));
            ByteArrayInputStream bisXml =  new ByteArrayInputStream(xmlFile);
            FileOutputStream fosBnux = new FileOutputStream("C:/projects/XML/data/DEMOFLORIDA.gml.bnux.new");
            ByteArrayOutputStream bos = b.xml2bnux(bisXml);
            byte[] byy = bos.toByteArray();
            fosBnux.write(byy);

            //BNUX2XML
            byte[] bnuxFile = b.readFile(new File("C:/projects/XML/data/DEMOFLORIDA.gml.bnux.new"));
            ByteArrayInputStream bisBnux =  new ByteArrayInputStream(bnuxFile);
            FileOutputStream fosXml = new FileOutputStream("C:/projects/XML/data/DEMOFLORIDA.gml.new");
            bos = b.Bnux2Xml(bisBnux);
            byy = bos.toByteArray();
            fosXml.write(byy);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static String slurp (InputStream in) throws IOException {
        StringBuffer out = new StringBuffer();
        byte[] b = new byte[4096];
        for (int n; (n = in.read(b)) != -1;) {
            out.append(new String(b, 0, n));
        }
        return out.toString();
    }


}
